<template>
  <div ref="canvas"></div>
</template>

<script lang="ts" setup>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import Stats from "three/examples/jsm/libs/stats.module";
import { RectAreaLightUniformsLib } from "three/examples/jsm/lights/RectAreaLightUniformsLib";
import { ref, onMounted } from "vue";

// 画布
const canvas = ref<any>('');
// 场景RectAreaLight
const scene = new THREE.Scene();
// 相机
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(-50, 30, 50);
camera.lookAt(0,0,0);
// 渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor(0x000000);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// 相机控件
const orbitControl = new OrbitControls(camera, renderer.domElement);
// 性能统计
const stat = Stats();
// plane
const planeGeometry = new THREE.PlaneGeometry(70, 70, 1, 1);
const planeMaterial = new THREE.MeshStandardMaterial({
  roughness: 0.044676705160855, // calculated from shininess = 1000
  metalness: 0.0,
  side: THREE.DoubleSide,
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotateX(-0.5 * Math.PI);
plane.position.set(0, 0, 0);
// plane.receiveShadow = true;
// plane.castShadow = true;
scene.add(plane);
// spotLight
const spotLight = new THREE.SpotLight(0xcccccc);
spotLight.position.set(-40, 60, -10);
spotLight.intensity = 0.1;
spotLight.lookAt(plane.position);
scene.add(spotLight);

RectAreaLightUniformsLib.init();

// first AreaLight and Box
const firstAreaLight = new THREE.RectAreaLight(0xff0000, 500, 10, 10);
firstAreaLight.position.set(-10, 10, 35);
scene.add(firstAreaLight);

let firstBoxGeometry = new THREE.BoxGeometry(4, 10, 0);
let firstBoxMaterial = new THREE.MeshBasicMaterial({
  color: 0xff0000
});
let firstBox = new THREE.Mesh(firstBoxGeometry, firstBoxMaterial);
firstBox.position.copy(firstAreaLight.position);
scene.add(firstBox);

// second AreaLight and Box
const secondAreaLight = new THREE.RectAreaLight(0x00ff00, 500, 10, 10);
secondAreaLight.position.set(0, 10, 35);
scene.add(secondAreaLight);

let secondBoxGeometry = new THREE.BoxGeometry(4, 10, 0);
let secondBoxMaterial = new THREE.MeshBasicMaterial({
  color: 0x00ff00
});
let secondBox = new THREE.Mesh(secondBoxGeometry, secondBoxMaterial);
secondBox.position.copy(secondAreaLight.position);
scene.add(secondBox);

// third AreaLight and Box
const thirdAreaLight = new THREE.RectAreaLight(0x0000ff, 500, 10, 10);
thirdAreaLight.position.set(10, 10, 35);
scene.add(thirdAreaLight);

let thirdBoxGeometry = new THREE.BoxGeometry(4, 10, 0);
let thirdBoxMaterial = new THREE.MeshBasicMaterial({
  color: 0x0000ff
});
let thirdBox = new THREE.Mesh(thirdBoxGeometry, thirdBoxMaterial);
thirdBox.position.copy(thirdAreaLight.position);
scene.add(thirdBox);

// GUI
const controlObj = {
  rotationSpeed : 0.02,
  color1 : 0xff0000,
  intensity1 : 500,
  color2 : 0x00ff00,
  intensity2 : 500,
  color3 : 0x0000ff,
  intensity3 : 500,
};
const gui = new GUI();
gui.addColor(controlObj, 'color1').onChange(function (e) {
  firstAreaLight.color = new THREE.Color(e);
  firstBoxMaterial.color = new THREE.Color(e);
  scene.remove(firstBox);
  firstBox = new THREE.Mesh(firstBoxGeometry, firstBoxMaterial);
  firstBox.position.copy(firstAreaLight.position);
  scene.add(firstBox);
});
// @ts-ignore
gui.add(controlObj, 'intensity1', 0, 1000).onChange(function (e) {
  firstAreaLight.intensity = e;
});

gui.addColor(controlObj, 'color2').onChange(function (e) {
  secondAreaLight.color = new THREE.Color(e);
  secondBoxMaterial.color = new THREE.Color(e);
  scene.remove(secondBox);
  secondBox = new THREE.Mesh(secondBoxGeometry, secondBoxMaterial);
  secondBox.position.copy(secondAreaLight.position);
  scene.add(secondBox);
});
// @ts-ignore
gui.add(controlObj, 'intensity2', 0, 1000).onChange(function (e) {
  secondAreaLight.intensity = e;
});

gui.addColor(controlObj, 'color3').onChange(function (e) {
  thirdAreaLight.color = new THREE.Color(e);
  thirdBoxMaterial.color = new THREE.Color(e);
  scene.remove(thirdBox);
  thirdBox = new THREE.Mesh(thirdBoxGeometry, thirdBoxMaterial);
  thirdBox.position.copy(thirdAreaLight.position);
  scene.add(thirdBox);
});
// @ts-ignore
gui.add(controlObj, 'intensity3', 0, 1000).onChange(function (e) {
  thirdAreaLight.intensity = e;
});


// 渲染函数
const render = () => {
  stat.update();
  orbitControl.update();

  requestAnimationFrame(render);
  renderer.render(scene, camera);
};

onMounted(() => {
  canvas.value.appendChild(stat.domElement);
  canvas.value.appendChild(renderer.domElement);
  render();
});

</script>